home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
051-075
/
disk_053
/
compiler
/
genstmt.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-06
|
11KB
|
391 lines
#include <stdio.h>
#include "c.h"
#include "expr.h"
#include "gen.h"
#include "cglbdec.h"
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
int breaklab;
int contlab;
int retlab;
extern TYP stdfunc;
extern struct amode push[], pop[];
struct amode *makedreg(r)
/*
* make an address reference to a data register.
*/
int r;
{ struct amode *ap;
ap = xalloc(sizeof(struct amode));
ap->mode = am_dreg;
ap->preg = r;
return ap;
}
struct amode *makeareg(r)
/*
* make an address reference to an address register.
*/
int r;
{ struct amode *ap;
ap = xalloc(sizeof(struct amode));
ap->mode = am_areg;
ap->preg = r;
return ap;
}
struct amode *make_mask(mask)
/*
* generate the mask address structure.
*/
int mask;
{ struct amode *ap;
ap = xalloc(sizeof(struct amode));
ap->mode = am_mask;
ap->offset = mask;
return ap;
}
struct amode *make_direct(i)
/*
* make a direct reference to an immediate value.
*/
int i;
{ return make_offset(makenode(en_icon,i,0));
}
struct amode *make_strlab(s)
/*
* generate a direct reference to a string label.
*/
char *s;
{ struct amode *ap;
ap = xalloc(sizeof(struct amode));
ap->mode = am_direct;
ap->offset = makenode(en_nacon,s,0);
return ap;
}
genwhile(stmt)
/*
* generate code to evaluate a while statement.
*/
struct snode *stmt;
{ int lab1, lab2;
initstack(); /* initialize temp registers */
lab1 = contlab; /* save old continue label */
lab2 = breaklab; /* save old break label */
contlab = nextlabel++; /* new continue label */
gen_label(contlab);
if( stmt->s1 != 0 ) /* has block */
{
breaklab = nextlabel++;
initstack();
falsejp(stmt->exp,breaklab);
genstmt(stmt->s1);
gen_code(op_bra,0,make_label(contlab),0);
gen_label(breaklab);
breaklab = lab2; /* restore old break label */
}
else /* no loop code */
{
initstack();
truejp(stmt->exp,contlab);
}
contlab = lab1; /* restore old continue label */
}
gen_for(stmt)
/*
* generate code to evaluate a for loop
*/
struct snode *stmt;
{ int old_break, old_cont, exit_label, loop_label;
old_break = breaklab;
old_cont = contlab;
loop_label = nextlabel++;
exit_label = nextlabel++;
contlab = loop_label;
initstack();
if( stmt->label != 0 )
gen_expr(stmt->label,F_ALL | F_NOVALUE
,natural_size(stmt->label));
gen_label(loop_label);
initstack();
if( stmt->exp != 0 )
falsejp(stmt->exp,exit_label);
if( stmt->s1 != 0 )
{
breaklab = exit_label;
genstmt(stmt->s1);
}
initstack();
if( stmt->s2 != 0 )
gen_expr(stmt->s2,F_ALL | F_NOVALUE,natural_size(stmt->s2));
gen_code(op_bra,0,make_label(loop_label),0);
breaklab = old_break;
contlab = old_cont;
gen_label(exit_label);
}
genif(stmt)
/*
* generate code to evaluate an if statement.
*/
struct snode *stmt;
{ int lab1, lab2, oldbreak;
lab1 = nextlabel++; /* else label */
lab2 = nextlabel++; /* exit label */
oldbreak = breaklab; /* save break label */
initstack(); /* clear temps */
falsejp(stmt->exp,lab1);
if( stmt->s1 != 0 && stmt->s1->next != 0 )
if( stmt->s2 != 0 )
breaklab = lab2;
else
breaklab = lab1;
genstmt(stmt->s1);
if( stmt->s2 != 0 ) /* else part exists */
{
gen_code(op_bra,0,make_label(lab2),0);
gen_label(lab1);
if( stmt->s2 == 0 || stmt->s2->next == 0 )
breaklab = oldbreak;
else
breaklab = lab2;
genstmt(stmt->s2);
gen_label(lab2);
}
else /* no else code */
gen_label(lab1);
breaklab = oldbreak;
}
gendo(stmt)
/*
* generate code for a do - while loop.
*/
struct snode *stmt;
{ int oldcont, oldbreak;
oldcont = contlab;
oldbreak = breaklab;
contlab = nextlabel++;
gen_label(contlab);
if( stmt->s1 != 0 && stmt->s1->next != 0 )
{
breaklab = nextlabel++;
genstmt(stmt->s1); /* generate body */
initstack();
truejp(stmt->exp,contlab);
gen_label(breaklab);
}
else
{
genstmt(stmt->s1);
initstack();
truejp(stmt->exp,contlab);
}
breaklab = oldbreak;
contlab = oldcont;
}
call_library(lib_name)
/*
* generate a call to a library routine.
*/
char *lib_name;
{ SYM *sp;
sp = gsearch(lib_name);
if( sp == 0 )
{
++global_flag;
sp = xalloc(sizeof(SYM));
sp->tp = &stdfunc;
sp->name = lib_name;
sp->storage_class = sc_external;
insert(sp,&gsyms);
--global_flag;
}
gen_code(op_jsr,0,make_strlab(lib_name),0);
}
genswitch(stmt)
/*
* generate a linear search switch statement.
*/
struct snode *stmt;
{ int curlab;
struct snode *defcase;
struct amode *ap;
curlab = nextlabel++;
defcase = 0;
initstack();
ap = gen_expr(stmt->exp,F_DREG | F_VOL,4);
if( ap->preg != 0 )
gen_code(op_move,4,ap,makedreg(0));
stmt = stmt->s1;
call_library("c%switch");
while( stmt != 0 )
{
if( stmt->s2 ) /* default case ? */
{
stmt->label = curlab;
defcase = stmt;
}
else
{
gen_code(op_dc,4,make_label(curlab),
make_direct(stmt->label));
stmt->label = curlab;
}
if( stmt->s1 != 0 && stmt->next != 0 )
curlab = nextlabel++;
stmt = stmt->next;
}
if( defcase == 0 )
gen_code(op_dc,4,make_direct(0),make_label(breaklab));
else
gen_code(op_dc,4,make_direct(0),make_label(defcase->label));
}
gencase(stmt)
/*
* generate all cases for a switch statement.
*/
struct snode *stmt;
{ while( stmt != 0 )
{
if( stmt->s1 != 0 )
{
gen_label(stmt->label);
genstmt(stmt->s1);
}
else if( stmt->next == 0 )
gen_label(stmt->label);
stmt = stmt->next;
}
}
genxswitch(stmt)
/*
* analyze and generate best switch statement.
*/
struct snode *stmt;
{ int oldbreak;
oldbreak = breaklab;
breaklab = nextlabel++;
genswitch(stmt);
gencase(stmt->s1);
gen_label(breaklab);
breaklab = oldbreak;
}
genreturn(stmt)
/*
* generate a return statement.
*/
struct snode *stmt;
{ struct amode *ap;
if( stmt != 0 && stmt->exp != 0 )
{
initstack();
ap = gen_expr(stmt->exp,F_ALL,4);
if( ap->mode != am_dreg || ap->preg != 0 )
gen_code(op_move,4,ap,makedreg(0));
}
if( retlab == -1 )
{
retlab = nextlabel++;
gen_label(retlab);
if( save_mask != 0 )
gen_code(op_movem,4,pop,make_mask(save_mask));
gen_code(op_unlk,0,makeareg(6),0);
gen_code(op_rts,0,0,0);
}
else
gen_code(op_bra,0,make_label(retlab),0);
}
genstmt(stmt)
/*
* genstmt will generate a statement and follow the next pointer
* until the block is generated.
*/
struct snode *stmt;
{ while( stmt != 0 )
{
switch( stmt->stype )
{
case st_label:
gen_label(stmt->label);
break;
case st_goto:
gen_code(op_bra,0,make_label(stmt->label),0);
break;
case st_expr:
initstack();
gen_expr(stmt->exp,F_ALL | F_NOVALUE,
natural_size(stmt->exp));
break;
case st_return:
genreturn(stmt);
break;
case st_if:
genif(stmt);
break;
case st_while:
genwhile(stmt);
break;
case st_for:
gen_for(stmt);
break;
case st_continue:
gen_code(op_bra,0,make_label(contlab),0);
break;
case st_break:
gen_code(op_bra,0,make_label(breaklab),0);
break;
case st_switch:
genxswitch(stmt);
break;
default:
printf("DIAG - unknown statement.\n");
break;
}
stmt = stmt->next;
}
}
genfunc(stmt)
/*
* generate a function body.
*/
struct snode *stmt;
{ retlab = contlab = breaklab = -1;
if( lc_auto & 1 ) /* if frame size odd */
++lc_auto; /* make it even */
gen_code(op_link,0,makeareg(6),make_immed(-lc_auto));
opt1(stmt);
genstmt(stmt);
genreturn(0);
}